package com.zbest.zpay.acctrans.biz.service.impl;

import java.util.Date;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.zbest.common.lang.util.CoreDateUtils;
import com.zbest.zpay.acctrans.common.exception.AccTransRuntimeException;
import com.zbest.zpay.acctrans.dal.model.AccountMap;
import com.zbest.zpay.acctrans.dal.model.TransJnl;
import com.zbest.zpay.acctrans.enums.ActAttrFlag;
import com.zbest.zpay.acctrans.enums.HoldFlag;
import com.zbest.zpay.acctrans.enums.MainActTyp;
import com.zbest.zpay.acctrans.enums.TxMod;
import com.zbest.zpay.acctrans.enums.TxSts;
import com.zbest.zpay.acctrans.enums.biz.AcctransBizCode;
import com.zbest.zpay.acctrans.service.facade.AcctransOperationService;
import com.zbest.zpay.acctrans.service.model.AbstractAcctransRequest;
import com.zbest.zpay.acctrans.service.model.CommonResponse;
import com.zbest.zpay.acctrans.service.model.HoldEntity;
import com.zbest.zpay.acctrans.service.model.UnHoldEntity;
import com.zbest.zpay.acctrans.service.model.UserDepositRequest;
import com.zbest.zpay.acctrans.service.model.UserHoldDepositRequest;
import com.zbest.zpay.acctrans.service.model.UserHoldRequest;
import com.zbest.zpay.acctrans.service.model.UserUnHoldPlatformFeeRequest;
import com.zbest.zpay.acctrans.service.model.UserUnHoldRequest;
import com.zbest.zpay.acctrans.service.model.UserUnHoldTransferRequest;
import com.zbest.zpay.acctrans.service.model.UserUnHoldWithdrawRequest;
import com.zbest.zpay.acctrans.share.AccountMapService;
import com.zbest.zpay.acctrans.share.InitialTransactionService;
import com.zbest.zpay.acctrans.share.MasterAccountService;
import com.zbest.zpay.acctrans.share.OperationValidateService;
import com.zbest.zpay.acctrans.share.TxcdInfService;

/**
 * Created by wenfeihu on 16/5/25.
 */
@Service("acctransOperationService")
public class AcctransOperationServiceImpl implements AcctransOperationService {
    private static final Logger       logger = LoggerFactory
                                                 .getLogger(AcctransOperationServiceImpl.class);

    @Autowired
    private InitialTransactionService initialTransactionService;

    @Autowired
    private TxcdInfService            txcdInfService;

    @Autowired
    private OperationValidateService  operationValidateService;

    @Autowired
    private AccountMapService         accountMapService;

    @Autowired
    private MasterAccountService      masterAccountService;

    @Override
    public CommonResponse userHold(UserHoldRequest userHoldRequest) {
        logger.info("用户冻结的request:" + userHoldRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userHold(userHoldRequest);
            HoldEntity holdEntity = userHoldRequest.getHoldEntity();
            String txCd = holdEntity.getTxCd();
            String busTyp = holdEntity.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_H.getCode());
            if (StringUtils.isBlank(holdEntity.getHldNo())) {
                holdEntity.setHldNo(initialTransactionService.getHoldNo());
            }
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userHoldRequest);
            packTransJnlForHld(transJnl, holdEntity);
            initialTransactionService.init(transJnl);
            masterAccountService.holdHandler(transJnl, MainActTyp.USER_RMB.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setHldNo(transJnl.getHldNo());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户冻结的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户冻结的response:" + commonResponse.toString());
        return commonResponse;
    }

    @Override
    public CommonResponse userDeposit(UserDepositRequest userDepositRequest) {
        logger.info("用户存入的request:" + userDepositRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userDeposit(userDepositRequest);
            String txCd = userDepositRequest.getTxCd();
            String busTyp = userDepositRequest.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_DC.getCode());
            /** 查找会计分录 */
            AccountMap accountMap = accountMapService.queryAccountMap(txCd, busTyp);
            logger.info("获取的accountMap值:" + accountMap.toString());
            packTransJnl(transJnl, accountMap, null, userDepositRequest.getUsrId());
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userDepositRequest);
            initialTransactionService.init(transJnl);
            masterAccountService.handler(transJnl, HoldFlag.NONE.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户存入的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户存入的response:" + commonResponse.toString());
        return commonResponse;
    }

    @Override
    public CommonResponse userHoldDeposit(UserHoldDepositRequest userHoldDepositRequest) {
        logger.info("用户存入并冻结的request:" + userHoldDepositRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userHoldDeposit(userHoldDepositRequest);
            String txCd = userHoldDepositRequest.getTxCd();
            String busTyp = userHoldDepositRequest.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_DCH.getCode());
            if (StringUtils.isBlank(userHoldDepositRequest.getHoldEntity().getHldNo())) {
                userHoldDepositRequest.getHoldEntity().setHldNo(
                    initialTransactionService.getHoldNo());
            }
            /** 查找会计分录 */
            AccountMap accountMap = accountMapService.queryAccountMap(txCd, busTyp);
            logger.info("获取的accountMap值:" + accountMap.toString());
            packTransJnl(transJnl, accountMap, null, userHoldDepositRequest.getUsrId());
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userHoldDepositRequest);
            packTransJnlForHld(transJnl, userHoldDepositRequest.getHoldEntity());
            initialTransactionService.init(transJnl);
            masterAccountService.handler(transJnl, HoldFlag.HOLD.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setHldNo(transJnl.getHldNo());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户存入并冻结的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户存入并冻结的response:" + commonResponse.toString());
        return commonResponse;
    }

    @Override
    public CommonResponse userUnHold(UserUnHoldRequest userUnHoldRequest) {
        logger.info("用户解冻的request:" + userUnHoldRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userUnHold(userUnHoldRequest);
            UnHoldEntity unHoldEntity = userUnHoldRequest.getUnHoldEntity();
            String txCd = unHoldEntity.getTxCd();
            String busTyp = unHoldEntity.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_U.getCode());
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userUnHoldRequest);
            packTransJnlForUnHld(transJnl, unHoldEntity);
            initialTransactionService.init(transJnl);
            masterAccountService.unHoldHandler(transJnl, MainActTyp.USER_RMB.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setHldNo(transJnl.getHldNo());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户解冻的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户解冻的response:" + commonResponse.toString());
        return commonResponse;
    }

    @Override
    public CommonResponse userUnHoldTransfer(UserUnHoldTransferRequest userUnHoldTransferRequest) {
        logger.info("用户解冻并转账的request:" + userUnHoldTransferRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userUnHoldTransfer(userUnHoldTransferRequest);
            String txCd = userUnHoldTransferRequest.getTxCd();
            String busTyp = userUnHoldTransferRequest.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_UDC.getCode());
            /** 查找会计分录 */
            AccountMap accountMap = accountMapService.queryAccountMap(txCd, busTyp);
            logger.info("获取的accountMap值:" + accountMap.toString());
            packTransJnl(transJnl, accountMap, userUnHoldTransferRequest.getFromUsrId(),
                userUnHoldTransferRequest.getToUsrId());
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userUnHoldTransferRequest);
            packTransJnlForUnHld(transJnl, userUnHoldTransferRequest.getUnHoldEntity());
            initialTransactionService.init(transJnl);
            masterAccountService.handler(transJnl, HoldFlag.UNHOLD.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setHldNo(transJnl.getHldNo());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户解冻并转账的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户解冻并转账的response:" + commonResponse.toString());
        return commonResponse;
    }

    @Override
    public CommonResponse userUnHoldWithdraw(UserUnHoldWithdrawRequest userUnHoldWithdrawRequest) {
        logger.info("用户解冻并支取的request:" + userUnHoldWithdrawRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userUnHoldWithdraw(userUnHoldWithdrawRequest);
            String txCd = userUnHoldWithdrawRequest.getTxCd();
            String busTyp = userUnHoldWithdrawRequest.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_UDC.getCode());
            /** 查找会计分录 */
            AccountMap accountMap = accountMapService.queryAccountMap(txCd, busTyp);
            logger.info("获取的accountMap值:" + accountMap.toString());
            packTransJnl(transJnl, accountMap, userUnHoldWithdrawRequest.getUsrId(), null);
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userUnHoldWithdrawRequest);
            packTransJnlForUnHld(transJnl, userUnHoldWithdrawRequest.getUnHoldEntity());
            initialTransactionService.init(transJnl);
            masterAccountService.handler(transJnl, HoldFlag.UNHOLD.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setHldNo(transJnl.getHldNo());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户解冻并支取的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户解冻并支取的response:" + commonResponse.toString());
        return commonResponse;
    }

    @Override
    public CommonResponse userUnHoldPlatformFee(UserUnHoldPlatformFeeRequest userUnHoldPlatformFeeRequest) {
        logger.info("用户解冻支付平台费用的request:" + userUnHoldPlatformFeeRequest.toString());
        CommonResponse commonResponse = new CommonResponse();
        try {
            /** 校验输入参数的有效性 */
            operationValidateService.userUnHoldPlatformFee(userUnHoldPlatformFeeRequest);
            String txCd = userUnHoldPlatformFeeRequest.getTxCd();
            String busTyp = userUnHoldPlatformFeeRequest.getBusTyp();
            /** 判断交易码是否存在 */
            txcdInfService.isExist(txCd);
            TransJnl transJnl = new TransJnl();
            transJnl.setTxCd(txCd);
            transJnl.setBusTyp(busTyp);
            transJnl.setTxMod(TxMod.TX_MOD_UDC.getCode());
            /** 查找会计分录 */
            AccountMap accountMap = accountMapService.queryAccountMap(txCd, busTyp);
            logger.info("获取的accountMap值:" + accountMap.toString());
            packTransJnl(transJnl, accountMap, userUnHoldPlatformFeeRequest.getUsrId(), null);
            /** 预计流水 */
            packTransJnlForOrd(transJnl, userUnHoldPlatformFeeRequest);
            packTransJnlForUnHld(transJnl, userUnHoldPlatformFeeRequest.getUnHoldEntity());
            initialTransactionService.init(transJnl);
            masterAccountService.handler(transJnl, HoldFlag.UNHOLD.getCode());
            commonResponse.setJrnNo(transJnl.getJrnNo());
            commonResponse.setActDat(transJnl.getActDat());
            commonResponse.setHldNo(transJnl.getHldNo());
            commonResponse.setCode(AcctransBizCode.SUCCESS);
            commonResponse.setMessage(AcctransBizCode.SUCCESS.desc());
        } catch (AccTransRuntimeException e) {
            commonResponse.setCode(e.getBizCode());
            commonResponse.setMessage(e.getMessage());
        } catch (Exception e) {
            logger.error("用户解冻支付平台费用的异常", e);
            commonResponse.setCode(AcctransBizCode.SYSTEM_ERROR);
            commonResponse.setMessage(AcctransBizCode.SYSTEM_ERROR.desc());
        }
        logger.info("用户解冻支付平台费用的response:" + commonResponse.toString());
        return commonResponse;
    }

    private void packTransJnl(TransJnl transJnl, AccountMap accountMap, String fromUserId,
                              String toUerId) {
        transJnl.setSysDat(CoreDateUtils.yyyymmdd(new Date()));
        transJnl.setSysTim(CoreDateUtils.hh24miss(new Date()));
        transJnl.setDrActAttr(accountMap.getDrActAttr());
        transJnl.setDrActTyp(accountMap.getDrActTyp());
        if (StringUtils.equals(accountMap.getDrActAttr(), ActAttrFlag.ACCOUNT_ATTR_PER.getCode())
            || StringUtils
                .equals(accountMap.getDrActAttr(), ActAttrFlag.ACCOUNT_ATTR_MER.getCode())) {
            transJnl.setDrUsrId(fromUserId);
            transJnl.setDrActNo(MainActTyp.USER_RMB.getCode() + fromUserId);
        } else if (StringUtils.equals(accountMap.getDrActAttr(),
            ActAttrFlag.ACCOUNT_ATTR_MER.getCode())) {
            transJnl.setDrUsrId(fromUserId);
            transJnl.setDrActNo(MainActTyp.MERC_RMB.getCode() + fromUserId);
        } else {
            transJnl.setDrActNo(accountMap.getDrActNo());
        }

        transJnl.setCrActAttr(accountMap.getCrActAttr());
        transJnl.setCrActTyp(accountMap.getCrActTyp());
        if (StringUtils.equals(accountMap.getCrActAttr(), ActAttrFlag.ACCOUNT_ATTR_PER.getCode())) {
            transJnl.setCrUsrId(toUerId);
            transJnl.setCrActNo(MainActTyp.USER_RMB.getCode() + toUerId);
        } else if (StringUtils.equals(accountMap.getCrActAttr(),
            ActAttrFlag.ACCOUNT_ATTR_MER.getCode())) {
            transJnl.setCrUsrId(toUerId);
            transJnl.setCrActNo(MainActTyp.MERC_RMB.getCode() + toUerId);
        } else {
            transJnl.setCrActNo(accountMap.getCrActNo());
        }

    }

    private void packTransJnlForOrd(TransJnl transJnl,
                                    AbstractAcctransRequest abstractAcctransRequest) {
        transJnl.setOldTxDt(abstractAcctransRequest.getOldTxDt());
        transJnl.setOldTxTm(abstractAcctransRequest.getOldTxTm());
        transJnl.setOrdTyp(abstractAcctransRequest.getOrdTyp());
        transJnl.setOrdNo(abstractAcctransRequest.getOrdNo());
        transJnl.setOrdAmt(abstractAcctransRequest.getOrdAmt().getCent());
        transJnl.setFctTxAmt(abstractAcctransRequest.getFctTxAmt().getCent());
        transJnl.setFeeAmt(abstractAcctransRequest.getFeeAmt().getCent());
        transJnl.setVchNoTyp(abstractAcctransRequest.getVchNoTyp());
        transJnl.setVchNo(abstractAcctransRequest.getVchNo());
        transJnl.setRmk(abstractAcctransRequest.getTxDesc());
        transJnl.setBusCnl(abstractAcctransRequest.getBusCnl());
        transJnl.setSysCnl(abstractAcctransRequest.getSysCnl());
        transJnl.setState(TxSts.TX_STS_U.getCode());
        transJnl.setTxDesc(abstractAcctransRequest.getTxDesc());
    }

    private void packTransJnlForHld(TransJnl transJnl, HoldEntity holdEntity) {
        transJnl.setHldTxCd(holdEntity.getTxCd());
        transJnl.setHldBusTyp(holdEntity.getBusTyp());
        transJnl.setHldUsrId(holdEntity.getUsrId());
        transJnl.setHldCd(holdEntity.getHldCd());
        transJnl.setHldAmt(holdEntity.getHldAmt().getCent());
        transJnl.setHldNo(holdEntity.getHldNo());
        transJnl.setHldExpDt(holdEntity.getHldExpDt());
        transJnl.setHldExpTm(holdEntity.getHldExpTm());
        transJnl.setHldExpProcMod(holdEntity.getHldExpProcMod());
    }

    private void packTransJnlForUnHld(TransJnl transJnl, UnHoldEntity unHoldEntity) {
        transJnl.setHldTxCd(unHoldEntity.getTxCd());
        transJnl.setHldBusTyp(unHoldEntity.getBusTyp());
        transJnl.setHldUsrId(unHoldEntity.getUsrId());
        transJnl.setHldCd(unHoldEntity.getUnHldCd());
        transJnl.setHldAmt(unHoldEntity.getUnHldAmt().getCent());
        transJnl.setHldNo(unHoldEntity.getUnHldNo());
    }

}
